package it.polimi.jita.cp.block.dd;

import it.polimi.jita.cp.block.scheduler.IVirtualMachineSchedulerData;

import java.util.List;
import java.util.ListIterator;

import org.apache.commons.math3.distribution.GammaDistribution;
import org.apache.commons.math3.distribution.RealDistribution;

public class VirtualMachineData extends AbstractVirtualMachineData implements
		IVirtualMachineSchedulerData {

	Long intantsInThisState;
	ListIterator<Instant> iteratorInstants;

	public static RealDistribution TIME_ON_DISTRIBUTION = new GammaDistribution(20d, 19440d);

	protected VirtualMachineData(String name, Integer vCpuNum,
			Long intantsInThisState, List<Instant> instants) {
		super(name, vCpuNum, instants);
		this.intantsInThisState = intantsInThisState;
	}

	protected Instant nextInstant() {
		if (iteratorInstants != null) {
			setCurrentInstant(iteratorInstants.next());
		} else {
			resetInstantsIterator();
			setCurrentInstant(iteratorInstants.next());
		}

		return getCurrentInstant();
	}

	protected boolean hasNextInstant() {
		if (iteratorInstants != null)
			return iteratorInstants.hasNext();
		else
			resetInstantsIterator();

		return iteratorInstants.hasNext();
	}

	protected void resetInstantsIterator() {
		iteratorInstants = getInstants().listIterator();
	}

	@Override
	public Double getDemand() {
		if (DynamicDecisionMaker.PROBABILISTIC_METHOD && isLikelyDemand()) {
			double currentInstantDbl = iteratorInstants.nextIndex();
			double prob = (1 - TIME_ON_DISTRIBUTION
					.cumulativeProbability(currentInstantDbl
							+ intantsInThisState))
					/ (1 - TIME_ON_DISTRIBUTION
							.cumulativeProbability(currentInstantDbl));
			return getCurrentInstant().getDemand().doubleValue() * prob
					* getvCpuNum();
		}
		return getCurrentInstant().getDemand().doubleValue() * getvCpuNum();
	}

	@SuppressWarnings("unchecked")
	protected <T> List<T> getCastedInstants() {
		return (List<T>) (List<?>) getInstants();
	}

}
